﻿using System.Text;
using Lidgren.Network;
using NetBrick.Server;
using UniBrickCommon;
using UniBrickCommon.Packets;
using UniBrickServer.Utils;

namespace UniBrickServer.Handler
{
    public class AuthenticateHandler : PacketHandler
    {
        public AuthenticateHandler(Server server)
            : base(server)
        {
        }

        public override void Process(object packetData, BasePeer sender)
        {
            if (!sender.EncryptionAvailable) return;
            Log.Info("A user is trying to log in.");
            var peer = (UniBrickPeer) sender;
            var authenticatePacket = (AuthenticatePacket.Request) packetData;

            var success = true;
            var message = "Successfully authenticated.";

            if(peer.Authenticated)
            {
                success = false;
                message = "Already authenticated";
                Log.Info("User failed to log in - already authenticated.");
            }

            if (success && !PlayerUtils.UserExists(authenticatePacket.Username) ||
                PlayerUtils.GetPassword(authenticatePacket.Username) !=
                EncryptionUtils.Hash(Encoding.UTF8.GetString(sender.Decrypt(authenticatePacket.Password))))
            {
                success = false;
                message = "Invalid Credentials.";
                Log.Info("User failed to log in - invalid credentials.");
            }

            if(success && UniBrickServer.Instance.Players.ContainsKey(authenticatePacket.Username))
            {
                UniBrickServer.Instance.Players[authenticatePacket.Username].Kick("Logged in from another location.");
                UniBrickServer.Instance.Players.Remove(authenticatePacket.Username);
            }

            if (success)
            {
                peer.Authenticate(authenticatePacket.Username);
                message = peer.World;
                UniBrickServer.Instance.Players[authenticatePacket.Username] = peer;
            }

            var response = new AuthenticatePacket.Response(success, message, authenticatePacket.Username);
            Server.SendPacket(UniBrickPacketCode.AuthenticateResponse, response, peer, NetDeliveryMethod.ReliableOrdered);
        }
    }
}